package cn.biplam.front.template.control;

import java.util.ArrayList;

import cn.biplam.common.tools.TOOLS;
import cn.biplam.common.wrapper.ErrorMessage;
import cn.biplam.common.wrapper.sqlresult.SqlResult;
import cn.biplam.front.html.base.Html;
import cn.biplam.front.html.base.HtmlWindow;
import cn.biplam.front.template.control.table.TablePropertys;
import cn.biplam.front.template.control.table.TablePropertys.Table_Size;
import cn.biplam.front.template.control.table.cell.Cell;
import cn.biplam.front.template.control.table.cell.EmptyCell;
import cn.biplam.front.template.control.table.cell.InputCell;
import cn.biplam.front.template.control.table.cell.SelectCell;
import cn.biplam.front.template.control.table.cell.TextAreaCell;
import cn.biplam.front.template.control.table.cell.TextCell;

/**
 * 编辑界面自动布局表格，用于表记录的添加和修改时界面自动布局，可以与数据库一条记录绑定根据预先设定的单元格类型和表格占位大小返回自动布局界面
 * @author XiaoRuxing 2009-5-4下午10:14:47
 * @version 1.0
 */
public class EditTable {
	/** 表格 */
	private FlatTable table;
	/** 表格属性 */
	private TablePropertys propertys;

	/** 当前行宽度 */
	private int currentWidth;
	/** 当前列数 */
	private int currentCol;
	/** 最大列数 */
	private int maxCol=0;
	/** 所有单元格容器 */
	private ArrayList<ArrayList<HtmlWindow>> cells;
	/** 当前行单元格容器 */
	private ArrayList<HtmlWindow> row;

	/** 存储占用多行的单元格所占大小，宽度（像素）和高度（行数） */
	private ArrayList<int[]> cellSize;
	private ArrayList<ArrayList<Integer>> cellRowSpan;
	private ArrayList<Integer> rowSpan;
	/** 当前行最大宽度 */
	private int currentMaxWidth;
	/** 表格宽度 */
	private int tableWidth;
	/** 表格行数 */
	private int rowNum;

	/** 创建编辑界面表格
	 * @param tableID 表ID
	 * @param keyValue 主键值
	 * @param propertys 属性
	 * @throws ErrorMessage 
	 */
	public EditTable(String tableID,String keyValue,TablePropertys propertys,Table_Size tableSize) throws ErrorMessage{
		this.table=new FlatTable(tableID,keyValue);
		this.tableWidth=tableSize.toInt();
		this.propertys=propertys;
		_init();
	}

	private void _init(){
		this.cells=new ArrayList<ArrayList<HtmlWindow>>();
		currentCol=-1;
		currentWidth=0;
		rowNum=0;
		cellSize=new ArrayList<int[]>();
		cellRowSpan=new ArrayList<ArrayList<Integer>>();
		currentMaxWidth=tableWidth-10;
	}

	/** 根据传入数据生成编辑界面
	 * @param sr 数据
	 * @throws ErrorMessage 
	 */
	public void put(SqlResult sr) throws ErrorMessage{

		/** 单元格名称 */
		String colName=null;
		String content=null;
		for(int j=0;j<propertys.getColNumber();j++){
			colName=propertys.getColName(j);
			if(!propertys.isExtent(colName)){
				if(sr!=null && !sr.isNull()){
					content=sr.get(0,colName);
				}
				_putTableCell(j,content,colName);
			}else{
				_putTableCell(j,colName,colName);
			}
		}
	}

	/**
	 * 生成内容为空的添加数据界面
	 * @throws ErrorMessage
	 */
	public void putEmptyTable() throws ErrorMessage{
		SqlResult sr=null;
		put(sr);
	}

	/**
	 *  放置非行列对象的额外隐藏对象
	 * @param html
	 * @throws ErrorMessage 
	 */
	public void putExtend(Html html) throws ErrorMessage{
		this.table.putExtend(html);
	}
	
	/** 插入单元格
	 * @param content 单元格数据内容
	 * @throws ErrorMessage 
	 */
	private void _putTableCell(int col,String content,String colName) throws ErrorMessage{
		Cell cell=null;
		int cellHeight=0;
		int cellLength=0;
		//1. 获取单元格标题
		String cellTitle=null;
		cellTitle=propertys.getTableColTitle(col);
		//3. 获取单元格类型
		switch(propertys.getTableColType(col)){
		case NAME_TEXT: 
			cell=new TextCell(content,null);
			cellHeight=1;
			cellLength=cell.getLength();
			break;
		case INPUT_TEXT:
			cell=new InputCell(cellTitle,colName,content,currentMaxWidth);
			cellHeight=1;
			cellLength=cell.getLength();
			break;
		case INPUT_TEXT_AREA://设置单元格所占的行数为textArea的行数
			TextAreaCell tCell=new TextAreaCell(cellTitle,colName,content,currentMaxWidth,currentWidth);
			cellHeight=tCell.getHeight();
			cell=tCell;
			cellLength=cell.getLength();
			break;
		case BUTTON:
		case SELECT:
			HtmlWindow window=propertys.getExtentColumn(colName)[0];
			cellHeight=1;
			cell=new SelectCell(window,cellTitle);
			cellLength=cell.getLength();
			break;
		case RADIO:
		case RAIDO_GROUP:
		case CHECKBOX:
			cell=new EmptyCell();
			cellHeight=1;
			window=propertys.getExtentColumn(colName)[0];
			window.setMarginTop("3");
			cell.put(window);
			cellLength=window.getLength();
			break;
		}
		/** 遍历所有占用多行的单元格，如果该单元格没有占用当前行，则将当前最大行宽加上该单元格宽度 */
		for(int i=0;i<cellSize.size();i++){
			int[] cSize=cellSize.get(i);
			if(cSize[0]<=1){
				currentMaxWidth=currentMaxWidth+cSize[1];
			}
		}
		/** 如果当前行剩余宽度比单元格宽度小，换行(行下标加1，列下标为0，当前行宽为单元格宽) */
		if(currentCol<0 || currentMaxWidth-currentWidth<cellLength){
			/** 如果当前行的列数大于最大列数，设置最大列数为当前行列数 */
			if(currentCol>maxCol){
				maxCol=currentCol+1;
			}
			/** 新建一行 */
			row=new ArrayList<HtmlWindow>();
			rowSpan=new ArrayList<Integer>();
			/** 将新建的行放入行容器 */
			cells.add(row);
			cellRowSpan.add(rowSpan);
			/** 设置占用多行的单元格的占用行数 */
			for(int i=0;i<cellSize.size();i++){
				int[] cSize=cellSize.get(i);
				if(cSize[0]>1){
					cSize[0]--;
				}
			}
			rowNum=rowNum+cellHeight;
			/** 设置当前行列数0 */
			currentCol=0;
			/** 设置当前行所占宽度 */
			currentWidth=cellLength;
		}else{
			/** 设置当前行所占宽度 */
			currentWidth=cellLength+currentWidth;
			currentCol++;
		}

		/** 如果当前单元格的所占行数大于1并且单元格不是单独占一行，将单元格的占用行数和宽度放入队列 */
		if(cellHeight>1&&cellLength>=tableWidth){
			cellSize.add(new int[]{cellHeight,cellLength});
			currentMaxWidth=currentMaxWidth-cellLength;
		}
		//6.插入单元格
		row.add(cell.get());
		rowSpan.add(cellHeight);
	}

	/**
	 * 计算单元格所占列数，将所有单元格插入表中
	 * @throws ErrorMessage
	 */
	private void _generatorTable() throws ErrorMessage{

		/** 行的最大列数 */
		int[] rowMaxCol=new int[cells.size()];
		/** 初始化所有行最大列数为表格的最大列数 */
		for(int i=0;i<rowMaxCol.length;i++){
			rowMaxCol[i]=maxCol;
		}
		/** 行数 */
		int rowSize=cells.size();
		/** 读取每行的单元格，依次计算出单元格的colspan和rowspan,插入表格 */
		for(int i=0;i<rowSize;i++){
			/** 当前行单元格集合 */
			ArrayList<HtmlWindow> cr=cells.get(i);
			/** 当前行单元格的rowspan */
			ArrayList<Integer> cRowSpan=cellRowSpan.get(i);
			/** 当前行列数 */
			int colNum=cr.size();
			/** 初始化单元格colspan */
			int colspan=0;
			/** 初始化单元格rowspan */
			int rowspan=0;
			/** 行数加1 */
			for(int j=0;j<colNum;j++){
				_generatorColSize(colNum,rowMaxCol,colspan,rowspan,cRowSpan,rowSize,i,j,cr);
			}
		}
	}

	/**
	 * 计算当前单元格所占的行数和列数，插入到表格
	 * @throws ErrorMessage
	 */
	private void _generatorColSize(int colNum,int []rowMaxCol,int colspan,
			int rowspan,ArrayList<Integer> cRowSpan,int rowSize,int row,int col,ArrayList<HtmlWindow> crCell) throws ErrorMessage{

		/** 单元格colspan  */
		String sColspan=null;
		/** 单元格rowspan  */
		String sRowspan=null;
		
		/** 计算单元格所占列数，每个单元格所占列数为当前行最大列数整除当前行的单元格数，
		 * 当前行最后一列所占列数为普通单元格所占列数+最大列数与当前行单元格数的模（即将剩余列数加到最后一列） */
		if(col<colNum-1){
			colspan=rowMaxCol[row]/colNum;
		}else{
			colspan=rowMaxCol[row]/colNum+rowMaxCol[row]%colNum;
		}

		/**取得当前单元格的rowspan */
		rowspan=cRowSpan.get(col);
		/** 如果当前单元格所占行数大于1，则设置单元格的rowspan */
		if(rowspan>1){
			/** 如果当前行只有一列则设置rowspan等于1 */
			if(colNum<=1){
				rowNum=rowNum+rowspan-1;
				rowspan=1;
			}else{
				/** 如果当前单元格在最后一行则设置rowspan为1
				 * 否则：如果当前单元格行数+当前单元格所占行数>表格行数 设置当前行到表格最后一行的所有行的最大列数减1
				 *  如果当前单元格行数+当前单元格所占行数<表格行数 设置当前行之后的rowspan行的所有行的最大列数减1*/
				if(row>=rowSize-1){
					rowNum=rowNum+rowspan-1;
					rowspan=1;
				}else{
					for(int k=row+1;k<(row+rowspan>rowSize?rowSize:row+rowspan);k++){
						rowMaxCol[k]--;
					}	
				}
			}
			sRowspan=TOOLS.intToString(rowspan);
		}

		/** 如果当前单元格所占列数大于1，则设置单元格的colspan */
		if(colspan>1){
			sColspan=TOOLS.intToString(colspan);
		}
		table.putTd(crCell.get(col), row, col,sColspan,sRowspan);
	}

	/**
	 * 返回表格
	 * @return 
	 * @throws ErrorMessage
	 */
	public HtmlWindow get() throws ErrorMessage{
		_generatorTable();
		if(rowNum<3){
			rowNum=3;
		}
		table.setHeight(TOOLS.intToString(rowNum*18));
		table.setWidth(TOOLS.intToString(tableWidth));
		return table.get();
	}
}
